<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="姓名" prop="name">
        <el-input
          v-model="queryParams.name"
          placeholder="请输入姓名"
          clearable
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="el-icon-plus"
          size="mini"
          @click="handleAdd"
          v-hasPermi="['boss:blob:add']"
        >新增</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          icon="el-icon-edit"
          size="mini"
          :disabled="single"
          @click="handleUpdate"
          v-hasPermi="['boss:blob:edit']"
        >修改</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          plain
          icon="el-icon-delete"
          size="mini"
          :disabled="multiple"
          @click="handleDelete"
          v-hasPermi="['boss:blob:remove']"
        >删除</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="warning"
          plain
          icon="el-icon-download"
          size="mini"
          @click="handleExport"
          v-hasPermi="['boss:blob:export']"
        >导出</el-button>
      </el-col>
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
      <!-- 身份识别按钮 -->
    </el-row>

    <el-table v-loading="loading" :data="blobList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="主键ID" align="center" prop="id" />
      <el-table-column label="姓名" align="center" prop="name" />
      <el-table-column label="身份证号" align="center" prop="idCard" />
      <el-table-column label="人脸照片二进制数据" align="center" prop="facePhoto" />
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handleUpdate(scope.row)"
            v-hasPermi="['boss:blob:edit']"
          >修改</el-button>
          <el-button
            size="mini"
            type="text"
            icon="el-icon-delete"
            @click="handleDelete(scope.row)"
            v-hasPermi="['boss:blob:remove']"
          >删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    
    <pagination
      v-show="total>0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getList"
    />

    <!-- 添加或修改人脸注册信息（存二进制照片）对话框 -->
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="姓名" prop="name">
          <el-input v-model="form.name" placeholder="请输入姓名" />
        </el-form-item>
        <el-form-item label="身份证号" prop="idCard">
          <el-input v-model="form.idCard" placeholder="请输入身份证号" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">确 定</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>
   
  </div>
</template>

<script>
import { listBlob, getBlob, delBlob, addBlob, updateBlob } from "@/api/boss/blob"
import FileUpload from '@/components/FileUpload/index.vue'
import { idCardOcr, driverLicenseOcr, vehicleLicenseOcr } from "@/api/boss/ocr"

export default {
  name: "Blob",
  components: { FileUpload },
  data() {
    return {
      // 遮罩层
      loading: true,
      // 选中数组
      ids: [],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // 人脸注册信息（存二进制照片）表格数据
      blobList: [],
      // 弹出层标题
      title: "",
      // 是否显示弹出层
      open: false,
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        name: null,
      },
      // 身份识别表单
      dialogFormVisible:false,
      // 身份证识别
      idCardImageFile: null,
      idCardImageUrl: "",
      idCardLoading: false,
      idCardResult: null,
      idCardUploadVal: '',
      // 驾驶证识别
      driverLicenseImageFile: null,
      driverLicenseImageUrl: "",
      driverLicenseLoading: false,
      driverLicenseResult: null,
      driverUploadVal: '',
      // 行驶证识别
      vehicleLicenseImageFile: null,
      vehicleLicenseImageUrl: "",
      vehicleLicenseLoading: false,
      vehicleLicenseResult: null,
      vehicleUploadVal: '',
      // 身份證面別
      idCardSide: 'front',
      // 調試參數
      debug: { mode: 'file', key: 'file', keys: ['file','image','imgFile','uploadFile','multipartFile','base64','fileUrl'] },
      // 表单参数
      form: {},
      // 表单校验
      rules: {
        name: [
          { required: true, message: "姓名不能为空", trigger: "blur" }
        ],
        idCard: [
          { required: true, message: "身份证号不能为空", trigger: "blur" }
        ],
        createTime: [
          { required: true, message: "创建时间不能为空", trigger: "blur" }
        ]
      }
    }
  },
  created() {
    this.getList()
  },
  methods: {
    /** 查询人脸注册信息（存二进制照片）列表 */
    getList() {
      this.loading = true
      listBlob(this.queryParams).then(response => {
        this.blobList = response.rows
        this.total = response.total
        this.loading = false
      })
    },
    // 取消按钮
    cancel() {
      this.open = false
      this.reset()
    },
    // 身份识别按钮
    handleIdentityRecognition() {
      this.dialogFormVisible = true
    },
    // 通用上傳前校驗
    beforeUpload(file) {
      const isJPGOrPNG = file.type === "image/jpeg" || file.type === "image/png"
      const isLt5M = file.size / 1024 / 1024 < 5
      if (!isJPGOrPNG) {
        this.$message.error("上傳圖片只能是 JPG 或 PNG 格式!")
      }
      if (!isLt5M) {
        this.$message.error("上傳圖片大小不能超過 5MB!")
      }
      return isJPGOrPNG && isLt5M
    },
    // 嚴格符合後端的簡化 FormData（只附帶 file 與必要欄位）
    buildStrictFormData(imageFile, extra = {}) {
      const formData = new FormData()
      formData.append('file', imageFile)
      // 同時附帶常見鍵名 'image' 以兼容後端實現
      formData.append('image', imageFile)
      Object.keys(extra || {}).forEach(k => formData.append(k, extra[k]))
      return formData
    },
    // 逐鍵名嘗試的 OCR 調用，直到成功或全部失敗
    async performOcr(apiFunc, imageFile, extras = {}) {
      const extrasList = Array.isArray(extras) ? extras : [extras]
      const candidateKeys = ['file', 'image', 'imgFile', 'uploadFile', 'multipartFile']
      // 若手動指定了鍵名與提交方式，優先採用一次
      if (this.debug && this.debug.mode) {
        try {
          const fd = new FormData()
          if (this.debug.mode === 'file') {
            fd.append(this.debug.key || 'file', imageFile)
          } else if (this.debug.mode === 'fileUrl') {
            const first = extrasList[0] || {}
            if (first.fileUrl) fd.append(this.debug.key || 'fileUrl', first.fileUrl)
          } else if (this.debug.mode === 'base64') {
            const base64 = await this.fileToBase64(imageFile)
            fd.append(this.debug.key || 'base64', base64.split(',')[1] || base64)
          }
          Object.keys(extrasList[0] || {}).forEach(k => fd.append(k, extrasList[0][k]))
          const resp = await apiFunc(fd)
          if (resp && (resp.code === 200 || resp.success) && (resp.data || resp.result)) {
            return resp.data || resp.result
          }
        } catch (e) {}
      }
      for (let eIdx = 0; eIdx < extrasList.length; eIdx++) {
        const extra = extrasList[eIdx] || {}
        for (let i = 0; i < candidateKeys.length; i++) {
          const key = candidateKeys[i]
          const fd = new FormData()
          fd.append(key, imageFile)
          Object.keys(extra || {}).forEach(k => fd.append(k, extra[k]))
          try {
            const resp = await apiFunc(fd)
            if (resp && (resp.code === 200 || resp.success) && (resp.data || resp.result)) {
              return resp.data || resp.result
            }
          } catch (e) {
            // 繼續嘗試下一組參數
          }
        }
      }
      // 最後再嘗試 base64 方案
      try {
        const base64 = await this.fileToBase64(imageFile)
        for (let eIdx = 0; eIdx < extrasList.length; eIdx++) {
          const extra = extrasList[eIdx] || {}
          const fd = new FormData()
          fd.append('base64', base64.split(',')[1] || base64)
          Object.keys(extra || {}).forEach(k => fd.append(k, extra[k]))
          const resp = await apiFunc(fd)
          if (resp && (resp.code === 200 || resp.success) && (resp.data || resp.result)) {
            return resp.data || resp.result
          }
        }
      } catch (e) {}
      return null
    },
    // 讀取文件為 Base64 字串
    fileToBase64(file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.onload = () => resolve(reader.result)
        reader.onerror = reject
        reader.readAsDataURL(file)
      })
    },
    // 身份證識別
    handleIdCardFileChange(file) {
      this.idCardImageFile = file.raw
      this.idCardImageUrl = URL.createObjectURL(file.raw)
      this.idCardResult = null
    },
    async startIdCardRecognition() {
      // 若沒有本地檔案但有上傳後的URL，嘗試抓取為Blob
      if (!this.idCardImageFile && this.idCardUploadVal) {
        try {
          const url = Array.isArray(this.idCardUploadVal) ? this.idCardUploadVal[0] : String(this.idCardUploadVal).split(',')[0]
          const res = await fetch(url)
          const blob = await res.blob()
          this.idCardImageFile = new File([blob], 'idcard.jpg', { type: blob.type || 'image/jpeg' })
        } catch (e) {}
      }
      if (!this.idCardImageFile) {
        this.$message.warning("請先上傳身份證圖片")
        return
      }
      this.idCardLoading = true
      const sideUpper = this.idCardSide === 'front' ? 'FRONT' : 'BACK'
      try {
        let result = null
        if (this.idCardImageFile) {
          const fd = new FormData()
          fd.append('uploadFile', this.idCardImageFile)
          fd.append('side', sideUpper)
          result = await idCardOcr(fd).then(r => (r && (r.data || r.result)) || null).catch(() => null)
        } else if (this.idCardUploadVal) {
          const url = Array.isArray(this.idCardUploadVal) ? this.idCardUploadVal[0] : String(this.idCardUploadVal).split(',')[0]
          const fd = new FormData()
          fd.append('fileUrl', url)
          fd.append('side', sideUpper)
          result = await idCardOcr(fd).then(r => (r && (r.data || r.result)) || null).catch(() => null)
        }
        if (result) {
          this.idCardResult = result
          this.$message.success('身份證識別成功')
        } else {
          this.$message.error('身份證識別失敗，請重試')
        }
      } finally {
        this.idCardLoading = false
      }
    },
    // 駕駛證識別
    handleDriverLicenseFileChange(file) {
      this.driverLicenseImageFile = file.raw
      this.driverLicenseImageUrl = URL.createObjectURL(file.raw)
      this.driverLicenseResult = null
    },
    async startDriverLicenseRecognition() {
      if (!this.driverLicenseImageFile && this.driverUploadVal) {
        try {
          const url = Array.isArray(this.driverUploadVal) ? this.driverUploadVal[0] : String(this.driverUploadVal).split(',')[0]
          const res = await fetch(url)
          const blob = await res.blob()
          this.driverLicenseImageFile = new File([blob], 'driver.jpg', { type: blob.type || 'image/jpeg' })
        } catch (e) {}
      }
      if (!this.driverLicenseImageFile) {
        this.$message.warning("請先上傳駕駛證圖片")
        return
      }
      this.driverLicenseLoading = true
      try {
        let result = null
        if (this.driverLicenseImageFile) {
          const fd = new FormData()
          fd.append('uploadFile', this.driverLicenseImageFile)
          result = await driverLicenseOcr(fd).then(r => (r && (r.data || r.result)) || null).catch(() => null)
        } else if (this.driverUploadVal) {
          const url = Array.isArray(this.driverUploadVal) ? this.driverUploadVal[0] : String(this.driverUploadVal).split(',')[0]
          const fd = new FormData()
          fd.append('fileUrl', url)
          result = await driverLicenseOcr(fd).then(r => (r && (r.data || r.result)) || null).catch(() => null)
        }
        this.driverLicenseResult = result
        if (result) {
          this.$message.success('駕駛證識別成功')
        } else {
          this.$message.error('駕駛證識別失敗，請重試')
        }
      } finally {
        this.driverLicenseLoading = false
      }
    },
    // 行駛證識別
    handleVehicleLicenseFileChange(file) {
      this.vehicleLicenseImageFile = file.raw
      this.vehicleLicenseImageUrl = URL.createObjectURL(file.raw)
      this.vehicleLicenseResult = null
    },
    async startVehicleLicenseRecognition() {
      if (!this.vehicleLicenseImageFile && this.vehicleUploadVal) {
        try {
          const url = Array.isArray(this.vehicleUploadVal) ? this.vehicleUploadVal[0] : String(this.vehicleUploadVal).split(',')[0]
          const res = await fetch(url)
          const blob = await res.blob()
          this.vehicleLicenseImageFile = new File([blob], 'vehicle.jpg', { type: blob.type || 'image/jpeg' })
        } catch (e) {}
      }
      if (!this.vehicleLicenseImageFile) {
        this.$message.warning("請先上傳行駛證圖片")
        return
      }
      this.vehicleLicenseLoading = true
      try {
        let result = null
        if (this.vehicleLicenseImageFile) {
          const fd = new FormData()
          fd.append('uploadFile', this.vehicleLicenseImageFile)
          result = await vehicleLicenseOcr(fd).then(r => (r && (r.data || r.result)) || null).catch(() => null)
        } else if (this.vehicleUploadVal) {
          const url = Array.isArray(this.vehicleUploadVal) ? this.vehicleUploadVal[0] : String(this.vehicleUploadVal).split(',')[0]
          const fd = new FormData()
          fd.append('fileUrl', url)
          result = await vehicleLicenseOcr(fd).then(r => (r && (r.data || r.result)) || null).catch(() => null)
        }
        this.vehicleLicenseResult = result
        if (result) {
          this.$message.success('行駛證識別成功')
        } else {
          this.$message.error('行駛證識別失敗，請重試')
        }
      } finally {
        this.vehicleLicenseLoading = false
      }
    },
    // 表单重置
    reset() {
      this.form = {
        id: null,
        name: null,
        idCard: null,
        facePhoto: null,
        createTime: null
      }
      this.resetForm("form")
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.queryParams.pageNum = 1
      this.getList()
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.resetForm("queryForm")
      this.handleQuery()
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.id)
      this.single = selection.length!==1
      this.multiple = !selection.length
    },
    /** 新增按钮操作 */
    handleAdd() {
      this.reset()
      this.open = true
      this.title = "添加人脸注册信息（存二进制照片）"
    },
    /** 修改按钮操作 */
    handleUpdate(row) {
      this.reset()
      const id = row.id || this.ids
      getBlob(id).then(response => {
        this.form = response.data
        this.open = true
        this.title = "修改人脸注册信息（存二进制照片）"
      })
    },
    /** 提交按钮 */
    submitForm() {
      this.$refs["form"].validate(valid => {
        if (valid) {
          if (this.form.id != null) {
            updateBlob(this.form).then(response => {
              this.$modal.msgSuccess("修改成功")
              this.open = false
              this.getList()
            })
          } else {
            addBlob(this.form).then(response => {
              this.$modal.msgSuccess("新增成功")
              this.open = false
              this.getList()
            })
          }
        }
      })
    },
    /** 删除按钮操作 */
    handleDelete(row) {
      const ids = row.id || this.ids
      this.$modal.confirm('是否确认删除人脸注册信息（存二进制照片）编号为"' + ids + '"的数据项？').then(function() {
        return delBlob(ids)
      }).then(() => {
        this.getList()
        this.$modal.msgSuccess("删除成功")
      }).catch(() => {})
    },
    /** 导出按钮操作 */
    handleExport() {
      this.download('boss/blob/export', {
        ...this.queryParams
      }, `blob_${new Date().getTime()}.xlsx`)
    }
  }
}
</script>
<style>
  .text {
    font-size: 14px;
  }

  .item {
    padding: 18px 0;
  }

  .box-card {
    width: 480px;
  }
</style>